home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
predicates.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-10
|
19KB
|
836 lines
/* predicates.c */
#include "copyright.h"
/* Predicates for testing various conditions */
#include <stdio.h>
#include <varargs.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include "config.h"
#include "externs.h"
#include "db.h"
#include "interface.h"
#include "globals.h"
#include "ansi.h"
extern int first_free; /* free object list, from destroy.c */
char *tprintf(va_alist)
va_dcl
{
/* this is a generic function used to generate a format string */
static char buff[BUFFER_LEN*2]; /* safety margin */
va_list args;
char *fmt;
va_start(args);
fmt = va_arg(args, char *);
(void)vsprintf(buff, fmt, args);
buff[BUFFER_LEN - 1] = '\0';
return (buff);
}
int could_doit(player, thing)
dbref player;
dbref thing;
{
/* lock evaluation -- determines if player passes lock on thing, for
* the purposes of picking up an object or moving through an exit
*/
if (Typeof(thing) != TYPE_ROOM && db[thing].location == NOTHING)
return 0;
return (eval_boolexp(player, db[thing].key, thing, 0, BASICLOCK));
}
void did_it(player, thing, what, def, owhat, odef, awhat, loc)
dbref player;
dbref thing;
char *what;
char *def;
char *owhat;
char *odef;
char *awhat;
dbref loc;
{
/* executes the @attr, @oattr, @aattr for a command - gives a message
* to the enactor and others in the room with the enactor, and executes
* an action.
*/
ATTR *d;
char *tbuf1;
char tbuf2[BUFFER_LEN];
loc = (loc == NOTHING) ? db[player].location : loc;
/* only give messages if the location is good */
if (GoodObject(loc)) {
/* message to player */
if (what && *what) {
d = atr_get(thing, what);
if (d) {
strcpy(tbuf2,uncompress(d->value));
tbuf1 = exec(thing, player, 0, tbuf2);
notify(player, tbuf1);
free(tbuf1);
} else if (def && *def)
notify(player, def);
}
/* message to neighbors */
if (!Dark(player)) {
if (owhat && *owhat) {
d = atr_get(thing, owhat);
if (d) {
strcpy(tbuf2, uncompress(d->value));
tbuf1 = exec(thing, player, 0, tbuf2);
notify_except2(db[loc].contents, player, thing,
tprintf("%s %s", db[player].name, tbuf1));
free(tbuf1);
} else {
if (odef && *odef) {
notify_except2(db[loc].contents, player, thing,
tprintf("%s %s", (int) db[player].name,
(int) odef));
}
}
}
}
}
/* always do the action attribute if there is one (so things like
* rooms can @trigger) */
if (awhat && *awhat && (d = atr_get(thing, awhat))) {
ATTR *b;
strcpy(tbuf2, uncompress(d->value));
/* check if object has # of charges */
b = atr_get_noparent(thing, "CHARGES");
if (!b) {
/* no charges set, just execute the action */
parse_que(thing, tbuf2, player);
return;
} else {
int num = atoi(b->value);
if (num) {
/* charges left, decrement and execute */
(void) atr_add(thing, "CHARGES", tprintf("%d", num - 1),
db[b->creator].owner, NOTHING);
parse_que(thing, tbuf2, player);
return;
} else if (!(d = atr_get(thing, "RUNOUT")))
/* no charges left and no runout; do nothing */
return;
/* no charges left, execute runout */
strcpy(tbuf2, uncompress(d->value));
parse_que(thing, tbuf2, player);
}
}
}
int can_see(player, thing, can_see_loc)
dbref player;
dbref thing;
int can_see_loc;
{
/*
* 1) your own body isn't listed in a 'look' 2) exits aren't listed in a
* 'look' 3) unconnected (sleeping) players aren't listed in a 'look'
*/
if (player == thing ||
Typeof(thing) == TYPE_EXIT ||
((Typeof(thing) == TYPE_PLAYER) &&
!IS(thing, TYPE_PLAYER, PLAYER_CONNECT)))
return 0;
/* if the room is lit, you can see any non-dark objects */
else if (can_see_loc)
return (!Dark(thing));
/* otherwise room is dark and you can't see a thing */
else
return 0;
}
int controls(who, what)
dbref who;
dbref what;
{
/* Wizard controls everything
* owners control their stuff
* something which is in the enterlock of a ZMO controls non-INHERIT
* and non-player objects.
* INHERIT checks between two objects are checked in the code for the
* specific function in question (do_trigger, do_set, etc.)
* Those who pass the enterlock of a ZoneMaster control his objects.
*/
if (!GoodObject(what))
return 0;
if (Owns(who, what) || Wizard(who))
return 1;
if ((Zone(what) != NOTHING) &&
(Typeof(what) != TYPE_PLAYER) && !(Flags(what) & INHERIT) &&
(eval_boolexp(who, Enterkey(Zone(what)), what, 0, ENTERLOCK)))
return 1;
if (ZMaster(Owner(what)) &&
(eval_boolexp(who, Enterkey(Owner(what)), what, 0, ENTERLOCK)))
return 1;
return 0;
}
int can_pay_fees(who, pennies)
dbref who;
int pennies;
{
/* does who have enough pennies to pay for something, and if something
* is being built, does who have enough quota? Wizards and royalty
* aren't subject to either, and immortals aren't subject to the former.
*/
#ifdef QUOTA
int pay_quota();
#endif /* QUOTA */
/* don't do any checks if player is priv'ed */
if (NoPay(who))
return 1;
/* can't charge till we've verified building quota */
if (Pennies(Owner(who)) < pennies) {
notify(who, tprintf("Sorry, you don't have enough %s.", MONIES));
return 0;
}
/* check building quota */
#ifdef QUOTA
if (!pay_quota(who, QUOTA_COST)) {
notify(who, "Sorry, your building quota has run out.");
return 0;
}
#endif /* QUOTA */
/* check database size -- EVERYONE is subject to this! */
#ifdef BUILDING_LIMIT
if ((db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) {
notify(who, "Sorry, there is no more room in the database.");
return 0;
}
#endif /* BUILDING_LIMIT */
/* charge */
payfor(who, pennies);
return 1;
}
void giveto(who, pennies)
dbref who;
dbref pennies;
{
/* give who pennies */
/* wizards and royalty don't need pennies */
if (NoPay(who))
return;
who = Owner(who);
s_Pennies(who, Pennies(who) + pennies);
}
int payfor(who, cost)
dbref who;
int cost;
{
/* subtract cost from who's pennies */
dbref tmp;
if (NoPay(who))
return 1;
else if ((tmp = Pennies(Owner(who))) >= cost) {
s_Pennies(Owner(who), tmp - cost);
return 1;
} else
return 0;
}
#ifdef QUOTA
int get_current_quota(who)
dbref who;
{
/* figure out a player's quota. Add the RQUOTA attribute if he doesn't
* have one already. This function returns the REMAINING quota, not
* the TOTAL limit.
*/
ATTR *a;
int i;
int limit;
int owned = 0;
/* if he's got an RQUOTA attribute, his remaining quota is that */
a = atr_get_noparent(Owner(who), "RQUOTA");
if (a)
return (atoi(uncompress(a->value)));
/* else, count up his objects. If he has less than the START_QUOTA,
* then his remaining quota is that minus his number of current objects.
* Otherwise, it's his current number of objects. Add the attribute
* if he doesn't have it.
*/
for (i = 0; i < db_top; i++)
if (Owner(i) == Owner(who))
owned++;
owned--; /* don't count the player himself */
if (owned <= atoi(START_QUOTA))
limit = atoi(START_QUOTA) - owned;
else
limit = owned;
atr_add(Owner(who), "RQUOTA", tprintf("%d", limit), GOD, NOTHING);
return (limit);
}
void change_quota(who, payment)
dbref who;
int payment;
{
/* add or subtract from quota */
/* wizards and royalty don't need a quota */
if (NoPay(Owner(who)))
return;
atr_add(Owner(who), "RQUOTA",
tprintf("%d", get_current_quota(who) + payment),
GOD, NOTHING);
}
int pay_quota(who, cost)
dbref who;
int cost;
{
/* determine if we've got enough quota to pay for an object,
* and, if so, return true, and subtract from the quota.
*/
int curr;
/* wizards and royalty don't need a quota */
if (NoPay(Owner(who)))
return 1;
/* figure out how much we have, and if it's big enough */
curr = get_current_quota(who);
if (curr - cost < 0) /* not enough */
return 0;
change_quota(who, - cost);
return 1;
}
#endif /* QUOTA */
int name_wild_match(name, pattern)
const char *name, *pattern;
{
/* quick wildcard match on name */
if (*pattern == '\0')
return 0;
while (pattern && *pattern) {
switch (*pattern) {
case '*':
pattern++;
while ((*name) && (*name != '\0'))
name++;
break;
case '?':
pattern++;
name++;
break;
default:
if (UPCASE(*pattern) != UPCASE(*name))
return 0;
name++;
pattern++;
}
}
return 1;
}
int forbidden_name(name)
const char *name;
{
/* checks to see if name is in the forbidden names file */
char buf[BUFFER_LEN], *newlin, *ptr;
FILE *fp;
fp = fopen(NAMES_FILE, "r");
while ((fp != NULL) && (!feof(fp))) {
fgets(buf, BUFFER_LEN, fp);
/* step on the newline */
if ((newlin = (char *) index(buf, '\n')) != NULL) *newlin = '\0';
ptr = buf;
if (!strcasecmp(name, ptr)) {
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
int ok_name(name)
const char *name;
{
/* is name valid for an object? */
while(name && *name && isspace(*name)) name++;
return (name
&& *name
&& *name != LOOKUP_TOKEN
&& *name != NUMBER_TOKEN
&& *name != NOT_TOKEN
&& !index(name, ARG_DELIMITER)
&& !index(name, AND_TOKEN)
&& !index(name, OR_TOKEN)
&& strcasecmp(name, "me")
&& strcasecmp(name, "home")
&& strcasecmp(name, "here"));
}
int ok_player_name(name)
const char *name;
{
/* is name okay for a player? */
const char *scan;
if (!ok_name(name) || forbidden_name(name) ||
strlen(name) > PLAYER_NAME_LIMIT)
return 0;
for (scan = name; *scan; scan++) {
if (!(isprint(*scan) && !isspace(*scan))) { /* was isgraph(*scan) */
return 0;
}
}
return(lookup_player(name) == NOTHING);
}
int ok_password(password)
const char *password;
{
/* is password an acceptable password? */
const char *scan;
if (*password == '\0')
return 0;
for (scan = password; *scan; scan++) {
if (!(isprint(*scan) && !isspace(*scan))) {
return 0;
}
}
return 1;
}
void sstrcat(string, app)
char *string;
char *app;
{
char *s;
char tbuf1[BUFFER_LEN];
if ((strlen(app) + strlen(string)) >= BUFFER_LEN)
return;
sprintf(tbuf1, "%s", app);
for (s = tbuf1; *s; s++)
if ((*s == ',') || (*s == ';'))
*s = ' ';
strcat(string, tbuf1);
}
/* for lack of better place the @switch code is here */
void do_switch(player, exp, argv, cause, first)
dbref player;
char *exp;
char *argv[];
dbref cause;
int first; /* 0, match all, 1, match first */
{
int any = 0, a;
char *buff;
if (!argv[1])
return;
/* now try a wild card match of buff with stuff in coms */
for (a = 1; (a < (MAX_ARG - 1)) && argv[a] && argv[a + 1]; a += 2) {
/* eval expression */
buff = exec(player, cause, EV_STRIP | EV_FCHECK, argv[a]);
/* check for a match */
if (local_wild_match(buff, exp)) {
if (first && any) {
/* terminate loop if only want first match */
free(buff);
break;
} else {
any = 1;
parse_que(player, argv[a + 1], cause);
free(buff);
}
} else {
free(buff);
}
}
/* do default if nothing has been matched */
if ((a < MAX_ARG) && !any && argv[a])
parse_que(player, argv[a], cause);
}
dbref parse_match_possessive(player, str)
dbref player;
char *str;
{
char *box; /* name of container */
char *obj; /* name of object */
dbref loc; /* dbref of container */
char name[BUFFER_LEN]; /* str would be destructively modified */
strcpy(name, str);
box = name;
/* check to see if we have an 's sequence */
if ((obj = (char *) index(name, '\'')) == NULL)
return NOTHING;
*obj++ = '\0'; /* terminate */
if ((*obj == NULL) || ((*obj != 's') && (*obj != 'S')))
return NOTHING;
/* skip over the 's' and whitespace */
do {
obj++;
} while (isspace(*obj));
/* we already have a terminating null, so we're okay to just do matches */
init_match(player, box, NOTYPE);
match_neighbor();
match_possession();
loc = match_result();
if (!GoodObject(loc))
return NOTHING;
/* now we match on the contents */
init_match(loc, obj, NOTYPE);
match_possession();
return (match_result());
}
void page_return(player, target, type, message, def)
dbref player;
dbref target;
char *type;
char *message;
char *def;
{
/* code for auto-return page - HAVEN, IDLE, and AWAY messages */
ATTR *d;
char *tbuf1 = NULL;
char tbuf2[BUFFER_LEN];
struct tm *ptr;
time_t t;
if (message && *message) {
d = atr_get(target, message);
if (d) {
strcpy(tbuf2, uncompress(d -> value));
tbuf1 = exec(target, target, 0, tbuf2);
t = time(NULL);
ptr = (struct tm *) localtime(&t);
notify(player, tprintf("%s message from %s: %s", type,
db[target].name, tbuf1));
if (tbuf1)
free(tbuf1);
#ifdef MILITARY_TIME
notify(target,
tprintf("[%d:%02d] %s message sent to %s.",
ptr->tm_hour, ptr->tm_min, type, db[player].name));
#else
notify(target,
tprintf("[%d:%02d] %s message sent to %s.",
ptr->tm_hour == 0 ? 12 : ptr->tm_hour > 12 ? (ptr->tm_hour - 12) :
ptr->tm_hour, ptr->tm_min, type, db[player].name));
#endif /* MILITARY_TIME */
} else if (def && *def)
notify(player, def);
}
}
dbref where_is(thing)
dbref thing;
{
/* returns "real" location of object. This is the location for players
* and things, source for exits, and NOTHING for rooms.
*/
if (!GoodObject(thing))
return NOTHING;
switch (Typeof(thing)) {
case TYPE_ROOM:
return NOTHING;
case TYPE_EXIT:
return Home(thing);
default:
return Location(thing);
}
}
int nearby(obj1, obj2)
dbref obj1;
dbref obj2;
{
/* returns 1 if obj1 is "nearby" object2. "Nearby" is defined as:
* obj1 is in the same room as obj2, obj1 is being carried by
* obj2, obj1 is carrying obj2. Returns 0 if object isn't nearby
* or the input is invalid.
*/
dbref loc1, loc2;
if (!GoodObject(obj1) || !GoodObject(obj2))
return 0;
loc1 = where_is(obj1);
if (loc1 == obj2)
return 1;
loc2 = where_is(obj2);
if ((loc2 == obj1) || (loc2 == loc1))
return 1;
return 0;
}
void do_verb(player, cause, arg1, argv)
dbref player;
dbref cause;
char *arg1;
char *argv[];
{
/* user-defined verbs */
dbref victim;
dbref actor;
char *sptr[10];
int i;
/* find the object that we want to read the attributes off
* (the object that was the victim of the command)
*/
/* our victim object can be anything */
init_match(player, arg1, NOTYPE);
match_everything();
victim = match_result();
if (victim == NOTHING) {
notify(player, "What was the victim of the verb?");
return;
}
/* find the object that executes the action */
init_match(player, argv[1], NOTYPE);
match_near_things();
actor = match_result();
if (actor == NOTHING) {
notify(player, "What do you want to do the verb?");
return;
}
/* Control check is fascist.
* First check: we don't want <actor> to do something involuntarily.
* Both victim and actor have to be controlled by the thing which did
* the @verb (for speed we do a WIZARD check first), or: cause controls
* actor plus the second check is passed.
* Second check: we need read access to the attributes.
* Either the player controls victim or the player
* must be priviledged, or the victim has to be VISUAL.
*/
if (!(Wizard(player) ||
(controls(player, victim) && controls(player, actor)) ||
((controls(cause, actor) && Can_Examine(player, victim))))) {
notify(player, "Permission denied.");
return;
}
/* we're okay. Now we copy our args into the stack, saving
* the old stack so we can restore it later.
*/
for (i = 0; i < 10; i++)
sptr[i] = wptr[i];
for (i = 0; i < 10; i++)
wptr[i] = argv[i + 7];
/* do the command, then restore the stack */
did_it(actor, victim,
upcasestr(argv[2]), argv[3], upcasestr(argv[4]), argv[5],
upcasestr(argv[6]), getloc(actor));
for (i = 0; i < 10; i++)
wptr[i] = sptr[i];
}
char *grep_util(thing, pattern, lookfor, len)
dbref thing;
char *pattern;
char *lookfor;
int len; /* strlen(lookfor) */
{
/* returns a list of attributes which match <pattern> on <thing>
* whose contents have <lookfor>
*/
char *tbuf1;
char *s, *bp;
int found;
ALIST *a;
tbuf1 = (char *) malloc(BUFFER_LEN + 1);
bp = tbuf1;
for (a = db[thing].list; a; a = AL_NEXT(a)) {
if (!AL_BAD(a) && wild_match(pattern, AL_NAME(a))) {
s = (char *) uncompress(AL_STR(a)); /* warning: static */
found = 0;
while (*s && !found) {
if (!strncmp(lookfor, s, len))
found = 1;
else
s++;
}
if (found) {
if (bp != tbuf1)
safe_chr(' ', tbuf1, &bp);
safe_str(AL_NAME(a), tbuf1, &bp);
}
}
}
*bp = '\0';
return tbuf1;
}
void do_grep(player, obj, lookfor, flag)
dbref player;
char *obj;
char *lookfor; /* this is an UNPARSED arg */
int flag; /* 0 for just list, 1 for hilites */
{
dbref thing;
char *pattern;
int len, d, found, rlen;
ALIST *a;
char *s, *tp;
char tbuf1[BUFFER_LEN];
char repl[BUFFER_LEN];
/* check this first */
if (flag && !ShowAnsi(player)) {
notify(player, "You must be set ANSI to use this option.");
return;
}
if ((len = strlen(lookfor)) < 1) {
notify(player, "What pattern do you want to grep for?");
return;
}
/* find the attribute pattern */
pattern = (char *) index(obj, '/');
if (!pattern)
pattern = (char *) "*"; /* set it to global match */
else
*pattern++ = '\0';
/* now we've got the object. match for it. */
init_match(player, obj, NOTYPE);
match_everything();
thing = noisy_match_result();
if (thing == NOTHING)
return;
if (!Can_Examine(player, thing)) {
notify(player, "Permission denied.");
return;
}
/* we can think of adding in the hilites like doing a find and replace */
sprintf(repl, "%s%s%s", ANSI_HILITE, lookfor, ANSI_NORMAL);
rlen = strlen(repl);
if (flag) {
for (a = db[thing].list; a; a = AL_NEXT(a)) {
found = 0;
if (!AL_BAD(a) && wild_match(pattern, AL_NAME(a))) {
s = (char *) uncompress(AL_STR(a)); /* warning: static */
for (d = 0; (d < BUFFER_LEN) && *s; ) {
if (!strncmp(lookfor, s, len)) {
found = 1;
if ((d + rlen) < BUFFER_LEN) {
strcpy(tbuf1 + d, repl);
d += rlen;
s += len;
} else
tbuf1[d++] = *s++;
} else
tbuf1[d++] = *s++;
}
tbuf1[d++] = 0;
}
/* if we got it, display it */
if (found)
notify(player, tprintf("%s%s [#%d%s%s %s",
ANSI_HILITE, AL_NAME(a), Owner(AL_CREATOR(a)),
(AL_FLAGS(a) & AF_LOCKED) ? "+]:" : "]:",
ANSI_NORMAL, tbuf1));
}
} else {
notify(player,
tprintf("The following attributes on %s have contents matching '%s':",
Name(thing), lookfor));
tp = grep_util(thing, pattern, lookfor, len);
notify(player, tp);
free(tp);
}
}